public class Main {
    public static void  func(int a){

    }
    public static void main(String[] args) {
       // ****泛型****
        //***什么是泛型***
        /* 泛型：就是适用于许多许多类型 。 从代码上讲，就是对类型实现了参数化
        * 传一个类型*/
        func(1);

        //引出泛型
        //实现一个类，类中包含一个数组成员，使得数组中可以存放任何类型的数据，也可以根据成员方法返回数组中的某一个下标的值
        //demo包里面

        // 泛型解决的问题
        // 存储数据的时候，可以帮我们进行自动的类型检查
        // 获取元素的时候，可以帮我们进行类型转换                 -->  都是在编译的时候

        // 是编译时期的一种机制，在运行的时候没有泛型的概念
        // 把类型作为参数传递 --> 个数，顺序什么都要对应

        // 泛型的主要目的就是：指定当前的容器，要持有什么类型的对象，让编译器去做检查

        //***语法***
        /* class 泛型类名称<类型形参列表>extend 继承类 //这里可以使用类型参数{
            //这可以使用类型参数
        }
        class ClassName<T1,T2,T3....Tn>extends ParentClass<T1>{
        //可以只使用部分类型参数
        }
        * */

        // 1.类名后的<T>代表占位符，表示当前类是一个泛型类
        // 规范类型的形参一般使用一个大写字母表示，常用的名称有：
            /* E表示Element
               K表示Key
               V表示Value
               N表示Number
               T表示Type
               S,U,V等等-第一、第二、第三、第四个类型
            * */
        // 2.泛型当中是不能new一个实例数组，不能new泛型类的数组
        // T[] ts = new T[5]; 这是不对的
        // demo包中的 public T[] obj1 = (T[])new Object[3]; 不是最好的解决方法，会有更合适的

        //3.<>里面加入指定类型
        //4.不需要进行强制类型转换
        //5.会帮助做类型检查


        //****泛型类的使用****
        // demo包里面Test里面的例子

        //****泛型是如何编译的****
        // 擦除机制:
        //在编译运行的时候把T擦除成了Object类

        // 那么为什么不能T[] ts = new T[5];这样写呢
        // 真正再写的时候还是用 public Object[] obj = new Object[3];

        // 其实还是想要一个具体类型的数组，刚开始我们无法提出具体类型的数组


        //****泛型的上界****
        // < E extends N >  这个语法就叫做泛型的上界 ， 代表将来指定的参数类型一定是实现了这个接口的
        // < E extends Number > E是Number的子类或者是Number本身
        // 泛型是没有下界的


        //****泛型的方法****

    }
}